package org.jamailia.core.component;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.Example;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.dao.DataAccessException;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.stereotype.Repository;

import java.io.Serializable;

/**
 * GenericDao.
 */
@Repository
public class GenericDao extends HibernateDaoSupport implements InitializingBean {

    private boolean allowCreateNew = true;

    protected void initDao() throws Exception {
        super.initDao();
        getHibernateTemplate().setFlushMode(HibernateTemplate.FLUSH_COMMIT);
    }

    public void setAllowCreateNew( boolean allowCreateNew ) {
        this.allowCreateNew = allowCreateNew;
    }

    public boolean isAllowCreateNew() {
        return allowCreateNew;
    }

    protected Session getCurrentSession() {
        return getSession(isAllowCreateNew());
    }

    public Serializable save( final Object modelObject ) throws DataAccessException {
        return getCurrentSession().save(modelObject);
    }

    public void update( final Object modelObject ) throws DataAccessException {
        getCurrentSession().update(modelObject);
    }

    public void merge( final Object modelObject ) throws DataAccessException {
        getCurrentSession().merge(modelObject);
    }

    public void saveOrUpdate( final Object modelObject ) throws DataAccessException {
        getCurrentSession().saveOrUpdate(modelObject);
    }

    public Object load( final Class clazz, final Long id ) throws DataAccessException {
        return getCurrentSession().load(clazz, id);
    }

    public Object get( final Class clazz, final Long id ) throws DataAccessException {
        return getCurrentSession().get(clazz, id);
    }

    public void delete( final Object modelObject ) throws DataAccessException {
        getCurrentSession().delete(modelObject);
    }

    public Query createQuery( String queryString ) {
        return getCurrentSession().createQuery(queryString);
    }

    public Query getNamedQuery( String queryName ) {
        return getCurrentSession().getNamedQuery(queryName);
    }

    public Criteria createCriteria( Class entityClass ) {
        return getCurrentSession().createCriteria(entityClass);
    }

    public void flush() {
        getCurrentSession().flush();
    }

    public void refresh( Object entity ) {
        getCurrentSession().refresh(entity);
    }

    public void clear() {
        getCurrentSession().clear();
    }

    public Example createExample( Object example ) {
        return Example.create(example);
    }

    public Criteria createCriteriaByExample( Object example, Class entityClass ) {
        Criteria criteria = createCriteria(entityClass);
        Example ex = createExample(example);
        if (ex != null) {
            criteria.add(ex);
        }
        return criteria;
    }

    public Criteria createCriteriaByExample( Object example ) {
        if (example != null) {
            return createCriteriaByExample(example, example.getClass());
        } else {
            return null;
        }
    }

}